package org.gongliang.jsmile.config.excel;

import java.io.File;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;

import javax.servlet.http.HttpServletResponse;

import org.apache.poi.hssf.usermodel.HSSFDataFormat;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.gongliang.jsmile.common.kit.DateKit;
import org.gongliang.jsmile.config.excel.filter.ExcelCellType;
import org.gongliang.jsmile.config.excel.filter.ExcelVersion;

import com.google.common.base.Preconditions;

import jodd.bean.BeanUtil;

/**
 * @category excel导出工具(也支持模板导出)
 * @author 龚亮
 * @date 2016-10-14 14:03:21
 */
@SuppressWarnings("all")
public class PoiExporter {

	private static final int MAX_ROWS = 65535;

	/**
	 * 导出参数设置
	 */
	private ExportParams exportParams;
	/**
	 * 模板导出（模板文件路径）
	 */
	private File templateFile;


	private List<?> data;


	public PoiExporter(List<?> data) {
		this.data = data;
	}

	public static PoiExporter init(List<?> data) {
		return new PoiExporter(data);
	}

	/**
	 * 导出excel到浏览器
	 * 
	 * @param filename
	 *            导出的文件名称
	 */
	public void export(HttpServletResponse response) throws Exception {
		response.setContentType("application/vnd.ms-excel;charset=utf-8"); // 改成输出excel文件
		String filename = java.net.URLEncoder.encode(exportParams.getSheetName(), "UTF-8");
		if (ExcelVersion.EXCEL_2003 == exportParams.getExcelVersion()) {
			response.setHeader("Content-disposition", "attachment; filename=" + filename + ".xls");// 03版本后缀xls，之后的xlsx
		} else {
			response.setHeader("Content-disposition", "attachment; filename=" + filename + ".xlsx");// 03版本后缀xls，之后的xlsx
		}
		export(response.getOutputStream());
	}

	/**
	 * 导出excel
	 */
	public void export(OutputStream out) throws Exception {
		Preconditions.checkNotNull(data, "data不能为空!");
		Preconditions.checkNotNull(exportParams.getSheetName(), "sheetName不能为空!");
		Preconditions.checkNotNull(exportParams.getColumns(), "columns不能为空!");
		Workbook wb = null;
		if (templateFile != null && templateFile.exists()) {
			wb = WorkbookFactory.create(templateFile);
		} else {
			Preconditions.checkNotNull(exportParams.getHeader(), "header不能为空!");
			if (exportParams.getCellTypes() != null) {
				Preconditions.checkArgument(
						exportParams.getHeader().length == exportParams.getColumns().length
								&& exportParams.getCellTypes().length == exportParams.getColumns().length,
						"header and columns and cellTypes'的长度应该一样的。" + "(cellTypes:"
								+ exportParams.getCellTypes().length + "header:" + exportParams.getHeader().length
								+ ",columns:" + exportParams.getColumns().length + ")");
			} else {
				Preconditions.checkArgument(exportParams.getHeader().length == exportParams.getColumns().length,
						"header and columns '的长度应该一样的。" + "(header:" + exportParams.getHeader().length + ",columns:"
								+ exportParams.getColumns().length + ")");
			}
			if (ExcelVersion.EXCEL_2003 == exportParams.getExcelVersion()) {
				wb = new HSSFWorkbook();
				Preconditions.checkArgument(data.size() < MAX_ROWS, "xls格式的excel最大支持65535行数据，请导出为xlsx格式的文件!");
			} else {
				wb = new XSSFWorkbook();
			}
		}

		Sheet sheet = null;
		if (templateFile != null && templateFile.exists()) {
			sheet = wb.getSheetAt(0);
		} else {
			sheet = wb.createSheet(exportParams.getSheetName());
			CellStyle style = exportParams.getExcelStyle().getTitleStyle(sheet);
			Row titleRow = sheet.createRow(0);
			titleRow.setHeight((short) 500);
			/*
			 * 填充表头内容
			 */
			for (int i = 0, lenH = exportParams.getHeader().length; i < lenH; i++) {
				Cell cell = titleRow.createCell(i);
				if (exportParams.getHeader()[i] != null) {
					int columnWidth = 6000;
					sheet.setColumnWidth(i, columnWidth);
				}
				cell.setCellValue(exportParams.getHeader()[i]);
				cell.setCellStyle(style);
			}
		}

		/*
		 * 填充表体内容
		 */
		CellStyle style2 = exportParams.getExcelStyle().getContentStyle(sheet);
		for (int i = 0, lenH = data.size(); i < lenH; i++) {
			Row bodyRow = sheet.createRow(i + exportParams.getHeaderRow());
			bodyRow.setHeight((short) 500);
			for (int j = 0; j < exportParams.getColumns().length; j++) {
				Cell cell = bodyRow.createCell(j);
				int columnWidth = 6000;
				sheet.setColumnWidth(j, columnWidth);
				Object value = BeanUtil.declared.getProperty(data.get(i), exportParams.getColumns()[j]);
				if (exportParams.getExcelFilter() != null) {
					value = exportParams.getExcelFilter().doFilter(exportParams.getColumns()[j], value, data.get(i));
				}
				setCellValue(cell, style2, value, j);

			}
		}

		wb.write(out);
		wb.close();
	}


	/**
	 * 填充单元格的值(处理一些时间、数值等格式问题)
	 */
	public void setCellValue(Cell cell, CellStyle style, Object value, int i) {
		if (exportParams.getCellTypes() != null && exportParams.getCellTypes().length > 0) {
			if (ExcelCellType.INT.equals(exportParams.getCellTypes()[i])) {
				cell.setCellValue(value != null ? value.toString() : null);
				style.setDataFormat(HSSFDataFormat.getBuiltinFormat("0"));
			} else if (ExcelCellType.FLOAT.equals(exportParams.getCellTypes()[i])) {
				cell.setCellValue(value != null ? Float.parseFloat(value.toString()) : null);
				style.setDataFormat(HSSFDataFormat.getBuiltinFormat("0.00"));
			} else if (ExcelCellType.DOUBLE.equals(exportParams.getCellTypes()[i])) {
				cell.setCellValue(value != null ? Double.parseDouble(value.toString()) : null);
				style.setDataFormat(HSSFDataFormat.getBuiltinFormat("0.00"));
			} else if (ExcelCellType.BIGDECIMAL.equals(exportParams.getCellTypes()[i])) {
				cell.setCellValue(value != null ? new BigDecimal(value.toString()).doubleValue() : null);
				style.setDataFormat(HSSFDataFormat.getBuiltinFormat("0.00"));
			} else if (ExcelCellType.DATE.equals(exportParams.getCellTypes()[i])) {
				cell.setCellValue(value != null ? DateKit.formatDate((Date) value, "yyyy-MM-dd") : null);
			} else if (ExcelCellType.DATETIME.equals(exportParams.getCellTypes()[i])) {
				cell.setCellValue(value != null ? DateKit.formatDate((Date) value, "yyyy-MM-dd HH:mm:ss") : null);
			} else {
				cell.setCellValue(value != null ? value.toString() : "");
				cell.setCellType(CellType.STRING);
			}
		} else {
			cell.setCellValue(value != null ? value.toString() : "");
			cell.setCellType(CellType.STRING);
		}
		cell.setCellStyle(style);
	}



	public PoiExporter templateFile(File templateFile) {
		if (templateFile != null && templateFile.exists()) {
			this.templateFile = templateFile;
		} else {
			throw new IllegalArgumentException("templateFile文件不存在！");
		}
		return this;
	}

	public PoiExporter exportParams(ExportParams exportParams) {
		if (exportParams != null) {
			this.exportParams = exportParams;
		}
		return this;
	}

	public ExportParams getExportParams() {
		return exportParams;
	}

	public void setExportParams(ExportParams exportParams) {
		this.exportParams = exportParams;
	}

}
